home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / p_misc / 7p203upp.exe / V203SRC.LZH / DECODE.C < prev    next >
C/C++ Source or Header  |  1992-07-12  |  17KB  |  576 lines

  1. #include "7plus.h"
  2. #include "globals.h"
  3.  
  4. /*
  5. *** First decode. If there already are CORs for that file, try correcting
  6. *** afterwards.
  7. ***
  8.  */
  9. int control_decode (char *name)
  10. {
  11.   int i, cor_exists;
  12.   char newname[MAXPATH];
  13.  
  14.   i = cor_exists = 0;
  15.   *_ext = EOS;
  16.  
  17.   fnsplit (name, _drive, _dir, _file, _ext);
  18.   sprintf (newname, "%s%s%s.cor", _drive, _dir, _file);
  19.  
  20.   if (!test_exist (newname))
  21.     cor_exists = 1;
  22.  
  23.   i = decode_file (name, cor_exists);
  24.   if ((i == 11 || i == 19) && cor_exists)
  25.     return (correct_meta (newname, 1));
  26.  
  27.   return (i);
  28. }
  29.  
  30. /*
  31. *** decode a file. create error report, if errors detected.
  32. ***
  33. ***
  34.  */
  35.  
  36. int decode_file (char *name, int flag)
  37. {
  38.   FILE     *in, *out;
  39.   int      part, _part, parts, _parts, _parts0;
  40.   int      c_line, c_line2, c_line3, f_lines, blocklines;
  41.   int      defect, rest, length, hcorrupted, ignored;
  42.   uint     csequence, crc;
  43.   long     binbytes, _binbytes, lines, rebuilt;
  44.   ulong    ftimestamp, line;
  45.   char     rline[81], *p, dummi[20], dummi2[81];
  46.   char     inpath[MAXFPATH], indexfile[MAXPATH], metafile[MAXPATH];
  47.   char     filename[13], srcname[MAXPATH], orgname[MAXFNAME];
  48.   char     orgname2[66], destname[13];
  49.   register i, j;
  50.  
  51.   *orgname = EOS;
  52.   in = out = NULLFP;
  53.   hcorrupted = ignored = 0;
  54.   ftimestamp = 0UL;
  55.  
  56.   /* Isolate input-path and filename */
  57.   fnsplit (name, _drive, _dir, _file, _ext);
  58.   sprintf (inpath, "%s%s", _drive, _dir);
  59.   build_DOS_name (_file);
  60.   build_DOS_name (_ext);
  61.   _file[8] = _ext[3] = EOS;
  62.  
  63.   /* Make up names for the meta- and indexfile */
  64.   sprintf (metafile,  "%s.7mf", _file);
  65.   sprintf (indexfile, "%s.7ix", _file);
  66.  
  67.   if (!test_exist (metafile))
  68.   {
  69.     printf ("\007Metafile '%s' already exists.\n", metafile);
  70.     return (19);
  71.   }
  72.  
  73.   /* Initialize index-info */
  74.   *index->filename  = *index->full_name  = EOS;
  75.   index->length     = index->timestamp   = 0UL;
  76.   index->splitsize  = 0;
  77.   for (i=0;i<4080;i++)
  78.     index->lines_ok[i] = 0UL;
  79.  
  80.   /* Find out, if it's a splitted file */
  81.   parts = 2;
  82.   sprintf (srcname, "%s%s.p01", inpath, _file);
  83.   if (test_exist (srcname))
  84.   {
  85.     parts = 1;
  86.     sprintf (srcname, "%s%s.7pl", inpath, _file);
  87.     if (test_exist (srcname))
  88.     {
  89.       sprintf (srcname, "%s.7pl/p01", _file);
  90.       printf (cant, srcname);
  91.       return (2);
  92.     }
  93.   }
  94.  
  95.   /* Open input file */
  96.   in = fopen (srcname, OPEN_READ_BINARY);
  97.  
  98.   /* Set I/O-buffering */
  99.   setvbuf (in, NULL, _IOFBF, buflen);
  100.  
  101.   printf ("\n-----------\nDecoding...\n-----------\n\n");
  102.  
  103.   defect = _parts0 = rest = length = 0;
  104.   lines = rebuilt = 0L;
  105.  
  106.   /* Loop for number of parts. */
  107.   for (part = 1; part < parts +1; part++)
  108.   {
  109.     if (part == 256)
  110.     {
  111.       printf ("\007\nMore than 255 parts not allowed. Break.\n");
  112.       kill_dest (in, out, metafile);
  113.       return (8);
  114.     }
  115.  
  116.     /* If more than 1 part, generate filename for messages and handling. */
  117.     if (parts == 1)
  118.       sprintf (filename, "%s.7pl", _file);
  119.     else
  120.       sprintf (filename, "%s.p%02x", _file, part);
  121.  
  122.     /* If we're already at part > 1, generate filename for next part. */
  123.     if (part != 1)
  124.     {
  125.       sprintf (srcname, "%s%s", inpath, filename);
  126.       if (!(in = fopen (srcname, OPEN_READ_BINARY)))
  127.       {
  128.         printf ("\007\n'%s': Not found. Break.\n", srcname);
  129.         printf ("\nYou must have all parts to be able to decode!\n");
  130.         printf ("              ===\n");
  131.         printf ("Get the missing files and try again.\n");
  132.  
  133.         kill_dest (in, out, metafile);
  134.         return (2);
  135.       }
  136.       setvbuf (in, NULL, _IOFBF, buflen);
  137.     }
  138.  
  139.     /* Read, until starting line is found. */
  140.     while ((p = my_fgets (rline, 80, in)) != NULL)
  141.     {
  142.       if (!strncmp (rline, " go_7+. ", 7))
  143.         break;
  144.     }
  145.     /* p == NULL? then no starting line found. File no good. */
  146.     if (!p)
  147.     {
  148.       printf ("\007'%s': 7PLUS-startline ", filename);
  149.       printf ("not found. Break.\n");
  150.       kill_dest (in, out, metafile);
  151.       return (3);
  152.     }
  153.  
  154.     if (!mcrc (rline, 0))
  155.       rebuild (rline, 1);
  156.  
  157.     /* Check if file went trough 7bit channel */
  158.     if (!strstr (rline, "\xb0\xb1"))
  159.     {
  160.       printf ("\007\n'%s':\nBit 8 has been stripped! Can't decode.\n", filename);
  161.       printf ("Please check all settings of your terminal and tnc regarding 8 bit transfer.\n");
  162.       printf ("You will have to re-read '%s' from the mailbox\n", filename);
  163.       printf ("after having corrected the settings.\n");
  164.       kill_dest (in, out, metafile);
  165.       return (9);
  166.     }
  167.  
  168.     /* Get info from 7PLUS header */
  169.     if(sscanf (rline+8, "%d %s %d %s %ld %s %s %s %s %s",
  170.             &_part, dummi, &_parts, destname,
  171.             &binbytes, dummi, dummi2, dummi, dummi, dummi) != 10)
  172.       hcorrupted = 1;
  173.     blocklines = get_hex (dummi2);
  174.     strlwr (destname);                  /* Convert to lower case */
  175.  
  176.     /* Set number of lines in this file */
  177.     f_lines = blocklines;
  178.     if (_part == _parts)
  179.       f_lines = (int) (((binbytes + 61) / 62) % blocklines);
  180.     if (!f_lines)
  181.       f_lines = blocklines;
  182.     f_lines--;
  183.  
  184.     if (strlen (dummi) == 5)
  185.       if (!mcrc(rline, 0))
  186.         hcorrupted = 1;
  187.  
  188.     if (!hcorrupted)
  189.     {
  190.       if (_part == 1)
  191.       {
  192.         _parts0  = _parts;
  193.         strcpy (index->filename, destname);
  194.         index->length  = binbytes;
  195.         index->splitsize = blocklines;
  196.       }
  197.  
  198.       if (_parts0 != _parts        || stricmp(index->filename, destname) ||
  199.           index->length != binbytes || index->splitsize != blocklines)
  200.         hcorrupted = 1;
  201.     }
  202.     if (hcorrupted)
  203.     {
  204.       printf ("'%s': Header is corrupted. Can't continue.\n", filename);
  205.       kill_dest (in, out, metafile);
  206.       return(5);
  207.     }
  208.     /* If first part, process filename, calculate how many valid binary bytes
  209.        are contained in last code line of last part, initialize index-info. */
  210.     if (_part == 1)
  211.     {
  212.  
  213.       *orgname2 = EOS;
  214.  
  215.       if (dummi[3] == '*')
  216.       {
  217.         my_fgets (rline, 80, in);
  218.         if (!mcrc (rline, 0))
  219.         {
  220.           printf ("\nExtended Filename corrupted. Using filename from header.\n");
  221.           strcpy (orgname2, index->filename);
  222.         }
  223.         else
  224.           sscanf (rline, "/%60[^/]", orgname2);
  225.       }
  226.  
  227.       strcpy (orgname,  index->filename);
  228.       if (extended == '*' && *orgname2)
  229.         strncpy (orgname, orgname2, (size_t)(MAXFNAME-1));
  230.       strcpy (index->full_name, orgname);
  231.  
  232.       rest = (int) (binbytes % 62);
  233.       if (!rest)
  234.         rest = 62;
  235.       parts = _parts; /* Set number of parts to decode. */
  236.     }
  237.  
  238.     /* Current file does not contain expected part */
  239.     if (_part != part)
  240.     {
  241.       printf ("\007'%s': File does not contain part %03d. Break.\n", filename, part);
  242.       kill_dest (in, out, metafile);
  243.       return (4);
  244.     }
  245.  
  246.     /* If first part, open metafile for writing. */
  247.     if (part == 1)
  248.     {
  249.       out = fopen (metafile, OPEN_WRITE_BINARY);
  250.       setvbuf (out, NULL, _IOFBF, buflen); /* As always, bufferize */
  251.       printf ("File         Pt# of# Errors Rebuilt   Status\n");
  252.       progress (filename, part, parts, 0, 0, "decoding...");
  253.     }
  254.  
  255.     c_line = c_line2 = -1;
  256.  
  257.     /* Now decode this part */
  258.     do
  259.     {
  260.       /* Get a line from code file */
  261.       p = my_fgets (rline, 80, in);
  262.  
  263.       /* If line starts with a space, check if it's the last line */
  264.       if (p && *rline == ' ')
  265.         if (!strncmp (rline, " stop_7+.", 8))
  266.         {
  267.           /* Get timespamp */
  268.           if (!ftimestamp && strchr (rline, '['))
  269.           {
  270.             if (!mcrc (rline, 0))
  271.             {
  272.               progress (filename, part, parts, lines, rebuilt, "### rebuilding a line ###");
  273.               rebuild (rline, 2);
  274.               progress (filename, part, parts, lines, rebuilt, "decoding...");
  275.             }
  276.             if (mcrc (rline, 0))
  277.             {
  278.               char dummy[30];
  279.  
  280.               if (sscanf (rline, " stop_7+. %s [%lX]",
  281.                                                      dummy, &ftimestamp) != 2)
  282.                 ftimestamp = 0UL;
  283.             }
  284.             index->timestamp = ftimestamp;
  285.           }
  286.           p = NULL; /* Last line, set end indicator */
  287.         }
  288.       if (p)
  289.       {
  290.         /* Calculate CRC */
  291.         csequence = 0;
  292.         for (i=0; i<64; i++)
  293.           csequence = crctab[csequence>>8] ^ (((csequence&255)<<8) |
  294.                                                                   (byte)p[i]);
  295.         csequence &= 0x3fff; /* strip calculated CRC to 14 bits */
  296.  
  297.         c_line3 = c_line;
  298.         /* Get crc from code line */
  299.         crc_n_lnum (&crc, &c_line, p);
  300.  
  301.         if (csequence != crc)
  302.         {
  303.           if (ignored &1)
  304.             progress (filename, part, parts, lines, rebuilt, "*** rebuilding a line ***");
  305.           else
  306.             progress (filename, part, parts, lines, rebuilt, "### rebuilding a line ###");
  307.           if (!rebuild (p, 0))
  308.           {
  309.             ignored++; /* Incorrect CRC. Ignore line. */
  310.             c_line = c_line3;
  311.             continue;
  312.           }
  313.  
  314.           rebuilt++;
  315.           progress (filename, part, parts, lines, rebuilt, "decoding...");
  316.           crc_n_lnum (&crc, &c_line, p);
  317.         }
  318.  
  319.         /* Number of valid binary bytes in this line. If it's the last line
  320.            of the last part, set it to the number precalculated earlier */
  321.         length = 62;
  322.         if (c_line == f_lines && part == parts)
  323.           length = rest;
  324.       }
  325.  
  326.       /* If file ends prematurely, set current line number to number of
  327.          lines in this part, so that the missing lines can be protocolled. */
  328.       if (!p && f_lines != c_line)
  329.         c_line = f_lines+2;
  330.  
  331.       /* If current line number is greater than previous one -> ok */
  332.       if (c_line > c_line2)
  333.       {
  334.         /* Difference is greater than 1, then line(s) must be missing. */
  335.         if (c_line2 != c_line-1)
  336.         {
  337.           defect = 1;
  338.  
  339.           /* Loop for number of missing or corrupted lines */
  340.           for (i = c_line2+1; i < c_line; i++)
  341.           {
  342.             progress (filename, part, parts, lines, rebuilt, "decoding...");
  343.             lines++; /* Number of missing or corrupted lines. */
  344.  
  345.             j = 62;
  346.             if (i == f_lines && part == parts)
  347.               j = rest;
  348.  
  349.             line = (long)(part-1) * index->splitsize +i;
  350.             index->lines_ok[(int)(line>>5)] += 1UL << (int)(line&31);
  351.  
  352.             /* Write fill-bytes into metafile */
  353.             for (;j;j--)
  354.               my_putc ( 0, out);
  355.  
  356.             if (i == f_lines)
  357.             {
  358.               length = 0;
  359.               break;
  360.             }
  361.           }
  362.         }
  363.         decode_n_write (out, rline, length);
  364.  
  365.         c_line2 = c_line; /* Memorize current line number */
  366.       }
  367.     }
  368.     while (p); /* Loop until current code file ends */
  369.  
  370.     progress (filename, part, parts, lines, rebuilt, "decoding...");
  371.  
  372.     fclose (in);
  373.   }
  374.   progress (filename, part-1, parts, lines, rebuilt, "done...");
  375.  
  376.   index->lines_left = lines;
  377.  
  378.   /* Get size of metafile */
  379.   _binbytes = ftell (out);
  380.  
  381.   if (out)
  382.     fclose (out);
  383.  
  384.   if (defect) /* write index-file and error report */
  385.     w_index_err (index, 0);
  386.   else
  387.   {
  388.     if (_binbytes == binbytes)
  389.     {
  390.       test_file (NULLFP, orgname, 1, MAXFNAME-1);
  391.       replace (orgname, metafile, ftimestamp);
  392.  
  393.       printf ("\n");
  394.  
  395.       if (autokill)
  396.         kill_em (_file, inpath, (parts==1)?"7pl":"p", "cor", "c", "err", "e");
  397.  
  398.       printf ("\nDecoding successful! '%s', %ld bytes.\n",
  399.                                                            orgname, binbytes);
  400.       return (0);
  401.     }
  402.   }
  403.  
  404.   printf ("\n");
  405.   if (!flag)
  406.   {
  407.     printf ("\nDecoding of '%s' not successful.\n", orgname);
  408.     if (index->lines_left > (index->length/620L))
  409.     {
  410.       printf ("\nWARNING:\n========\n");
  411.       printf ("More than 10%% of all lines are corrupted! Are you sure, your communications\n");
  412.       printf ("programm is set correctly to handle 7PLUS files (character conversion ect..)?\n");
  413.       printf ("Maybe you didn't get parts of the files because of link failures?\n");
  414.       printf ("Of course, the cause may lie with the originating source...\n\n");
  415.     }
  416.   }
  417.   if (_binbytes != binbytes)
  418.   {
  419.     printf ("\nDecoded file has wrong length! Disk full?\n");
  420.     printf ("This error should never have occured.....I hoped...\n");
  421.     return (1);
  422.   }
  423.   else
  424.     if (autokill)
  425.       kill_em (_file, inpath, (parts==1)?"7pl":"p", NULL, NULL, NULL, NULL);
  426.  
  427.   return (11);
  428. }
  429.  
  430.  
  431. /*
  432. ***
  433. *** split up longs into 2 * 31 binary bytes and write to file.
  434. ***
  435.  */
  436. void decode_n_write (FILE *out, char *p, int length)
  437. {
  438.   static ulong after[16], *af;
  439.   static int   i, j, k;
  440.  
  441.   /* Re-arrange data-characters to 2*8 longs containing 31 bits each.*/
  442.   for (i=k=0; i<64; i++)
  443.   {
  444.     if ((i&3) == 3)
  445.     {
  446.       after[k] = 0L;
  447.       for (j=i;j>(i-4);j--)
  448.         after[k] = after[k] * 216L + decode[(byte)p[j]];
  449.       k++;
  450.     }
  451.   }
  452.  
  453.   af = after;
  454.   for (i=0; i<2; i++, af+=8)
  455.   {
  456.     /* Re-arrange to 2*8 longs containing 32 bits.
  457.        7th and 15th long only contain 24 valid bits. */
  458.     af[0] = (af[0] << 1) | (af[1] >> 30);
  459.     af[1] = (af[1] << 2) | (af[2] >> 29);
  460.     af[2] = (af[2] << 3) | (af[3] >> 28);
  461.     af[3] = (af[3] << 4) | (af[4] >> 27);
  462.     af[4] = (af[4] << 5) | (af[5] >> 26);
  463.     af[5] = (af[5] << 6) | (af[6] >> 25);
  464.     af[6] = (af[6] << 7) | (af[7] >> 24);
  465.     af[7] = (af[7] << 8);
  466.     for(j=0; j<8; j++)
  467.     {
  468.       for (k=24;k;k-=8)
  469.       {
  470.         if (!length)
  471.           break;
  472.         length--;
  473.         my_putc ((int) (af[j] >> k), out);
  474.       }
  475.       if (j == 7 || !length)
  476.         break;
  477.       length--;
  478.       my_putc ((int) af[j], out);
  479.     }
  480.   }
  481. }
  482.  
  483. /*
  484. *** Write indexfile and error report
  485. ***
  486. ***
  487.  */
  488. void w_index_err (struct m_index *index, int flag)
  489. {
  490.   FILE *ifile;
  491.   char filename[13];
  492.  
  493.   if (!flag)
  494.   {
  495.     fnsplit (index->filename, NULL, NULL, filename, NULL);
  496.  
  497.     #ifndef _CHSIZE_OK
  498.      strcat (filename, ".7ix");
  499.      ifile = fopen (filename, OPEN_WRITE_BINARY);
  500.     #else
  501.      strcat (filename, ".7mf");
  502.      ifile = fopen (filename, OPEN_RANDOM_BINARY);
  503.     #endif
  504.     write_index (ifile, index, 0);
  505.     fclose (ifile);
  506.   }
  507.   fnsplit (index->filename, NULL, NULL, filename, NULL);
  508.   strcat (filename, ".err");
  509.   ifile = fopen (filename, OPEN_WRITE_TEXT);
  510.   strupr (filename);
  511.   fprintf (ifile, " go_text. %s%s", filename, delimit);
  512.   strcpy (filename, index->filename);
  513.   strupr (filename);
  514.   fprintf (ifile, "7PLUS error report: %s %03X", filename, index->splitsize);
  515.   if (strcmp (index->full_name, index->filename))
  516.     fprintf (ifile, " /%s/", index->full_name);
  517.   fprintf (ifile, " %ld%s", index->length, delimit);
  518.   write_index (ifile, index, 1);
  519.   fprintf (ifile, "[%lX]%s00%s", index->timestamp, delimit, delimit);
  520.   fprintf (ifile, "________%s stop_text.%s", delimit, delimit);
  521.   if (endstr)
  522.     fprintf (ifile, "%s%s", endstr, delimit);
  523.   fclose (ifile);
  524.  
  525.   fnsplit (index->filename, NULL, NULL, filename, NULL);
  526.   strcat (filename, ".err");
  527.   crc_file (filename, "7P", "00\n", 0);
  528. }
  529.  
  530. /*
  531. *** If an error report has been accidentally erased, it can be recreated
  532. *** using the information in the indexfile, respectively metafile.
  533. *** (depends on _CHSIZE_OK)
  534.  */
  535. int make_new_err (char *name)
  536. {
  537.   FILE   *rfile;
  538.  
  539.   printf ("-----------------------\nRecreating error report\n-----------------------\n\n");
  540.  
  541.   /* Open meta file */
  542.   if (!(rfile = fopen (name, OPEN_READ_BINARY)))
  543.   {
  544.     printf (cant, name);
  545.     return (2);
  546.   }
  547.  
  548.   /* read index info into struct index */
  549.   if (read_index (rfile, index))
  550.   {
  551.     printf ("\007Invalid index info.\n");
  552.     return (7);
  553.   }
  554.  
  555.   fclose (rfile);
  556.  
  557.   w_index_err (index, 1);
  558.  
  559.   printf ("Error report has been recreated from '%s'.\n", name);
  560.  
  561.   return (0);
  562. }
  563.  
  564. /*
  565. *** Progress indication
  566. ***
  567. ***
  568.  */
  569. void progress (char *filename, int part, int of_parts, long errors,
  570.                                                     long rebuilt, char *status)
  571. {
  572.   printf ("%-12s %3d %3d %6ld  %6ld   %-30s\r",
  573.     filename, part, of_parts, errors, rebuilt, status);
  574.   fflush (stdout);
  575. }
  576.